window.onload = function () {
  var container = document.getElementById("container");
  var canvas = document.createElement("canvas");
  canvas.width = container.clientWidth;
  canvas.height = container.clientHeight;
  container.appendChild(canvas);

  window.onresize = function () {
    canvas.width = container.clientWidth;
    canvas.height = container.clientHeight;
  };

  var gl = canvas.getContext("webgl");

  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
  var VERTEX_SHADER_SOURCE =
    'attribute vec4 a_Position;\n' +    //声明attribute变量a_Position，用来存放顶点位置信息；
    'attribute vec2 a_TexCoord;\n' +    //声明attribute变量a_TexCoord，用来存放纹理坐标；
    'varying vec2 v_TexCoord;\n' +      //声明varying变量v_TexCoord，用来向片元着色器传值纹理坐标；
    'void main(){\n' +
    'gl_Position = a_Position;\n' +     //变量a_Position赋值给顶点着色器内置变量gl_Position；
    'v_TexCoord = a_TexCoord;\n' +      //将纹理坐标传给片元着色器；
    '}\n';

  var FRAGMENT_SHADER_SOURCE =
    'precision mediump float;\n' +                          // float变量没有默认精度，所以使用前必须声明，否则会出错
    'uniform sampler2D u_Sampler;\n' +                      //声明uniform变量u_Sampler，用来存放纹理单元编号
    'varying vec2 v_TexCoord;\n' +                          //声明varying变量v_TexCoord，用来接收顶点着色器传送的纹理坐标
    'void main(){\n' +
    'gl_FragColor = texture2D(u_Sampler,v_TexCoord);\n' +   //使用texture2D函数抽取纹素，并赋值给内置变量gl_FragColor
    '}';
  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
  // 1.1创建顶点着色器对象
  var vertexShader = gl.createShader(gl.VERTEX_SHADER);
  // 1.2创建片元着色器对象
  var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  // 1.3引入顶点、片元着色器源代码
  gl.shaderSource(vertexShader, VERTEX_SHADER_SOURCE);
  gl.shaderSource(fragmentShader, FRAGMENT_SHADER_SOURCE);
  // 1.4编译顶点、片元着色器
  gl.compileShader(vertexShader);
  gl.compileShader(fragmentShader);
  // 1.5创建程序对象program
  var program = gl.createProgram();
  // 1.6附着顶点着色器和片元着色器到program
  gl.attachShader(program, vertexShader);
  gl.attachShader(program, fragmentShader);
  // 1.7链接program
  gl.linkProgram(program);
  // 1.8使用program
  gl.useProgram(program);
  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
  // 2.1初始化顶点坐标和颜色
  var verticesTexCoords = new Float32Array([
    -0.5, 0.5, 0.0, 1.0, //顶点1
    -0.5, -0.5, 0.0, 0.0, //顶点2
    0.5, 0.5, 1.0, 1.0, //顶点3
    0.5, -0.5, 1.0, 0.0, //顶点4
  ]);
  // 2.2创建缓冲区对象
  var vertexTexCoordBuffer = gl.createBuffer();
  // 2.3将顶点坐标和纹理坐标写入缓冲区对象
  gl.bindBuffer(gl.ARRAY_BUFFER, vertexTexCoordBuffer);
  gl.bufferData(gl.ARRAY_BUFFER, verticesTexCoords, gl.STATIC_DRAW);
  // 2.4获取类型化数组中每个元素的大小
  var FSIZE = verticesTexCoords.BYTES_PER_ELEMENT;
  // 2.5获取顶点着色器attribute变量a_Position的存储地址, 分配缓存并开启
  var a_Position = gl.getAttribLocation(program, 'a_Position');
  gl.vertexAttribPointer(a_Position, 2, gl.FLOAT, false, FSIZE * 4, 0);
  gl.enableVertexAttribArray(a_Position);
  // 2.6获取顶点着色器attribute变量a_TexCoord(纹理坐标)的存储地址, 分配缓存并开启
  var a_TexCoord = gl.getAttribLocation(program, 'a_TexCoord');
  gl.vertexAttribPointer(a_TexCoord, 2, gl.FLOAT, false, FSIZE * 4, FSIZE * 2);
  gl.enableVertexAttribArray(a_TexCoord);
  let n = verticesTexCoords.length / 4;
  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
  // ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
  //创建纹理对象
  var texture = gl.createTexture();
  //获取片元着色器uniform变量u_Sampler(纹理单元编号)的存储地址
  var u_Sampler = gl.getUniformLocation(program, 'u_Sampler');
  var image = new Image();
  image.src = './img.jpg' //设置纹理资源路径
  //注册加载事件的响应函数
  image.onload = function () {
    //调用加载纹理函数
    gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, 1);                                 //对纹理图像镜像y轴反转     
    gl.activeTexture(gl.TEXTURE0);                                             //激活纹理单元  
    gl.bindTexture(gl.TEXTURE_2D, texture);                                    //绑定纹理对象
    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);         //配置纹理对象参数
    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGB, gl.RGB, gl.UNSIGNED_BYTE, image);  //纹理图像分配给纹理对象
    gl.uniform1i(u_Sampler, 0);                                                //纹理单元编号传给片元着色器中uniform变量u_Sampler
    //清空canvas
    gl.clearColor(0.0, 0.0, 0.0, 1.0);
    gl.clear(gl.COLOR_BUFFER_BIT);
    //绘制纹理图像
    gl.drawArrays(gl.TRIANGLE_STRIP, 0, n)
  };
  // ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
}